package com.wonders.frame.service;

import com.gcr.util.StringUtil;
import com.wonders.frame.common.Enum.CommonSourceKeyEnum;
import com.wonders.frame.common.Enum.InitCommonSourceEnum;
import com.wonders.frame.common.Enum.RemovedCodeEnum;
import com.wonders.frame.common.QueryForm;
import com.wonders.frame.common.util.PageUtil;
import com.wonders.frame.entity.*;
import com.wonders.frame.entity.Tree.SelectTreeNodeData;
import com.wonders.frame.entity.form.AuthRoleForm;
import com.wonders.frame.repository.*;
import com.wonders.frame.repository.core.CoreRepository;
import com.wonders.frame.service.Core.CoreCurdService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestBody;

import javax.servlet.http.HttpServletRequest;
import javax.transaction.Transactional;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class AuthRoleService extends CoreCurdService<AuthRole> {
    Logger log = LoggerFactory.getLogger(AuthRoleService.class);

    @Autowired
    private AuthRoleRepository repo;

    protected CoreRepository getRepository() {
        return repo;
    }

    @Autowired
    private AuthRolePermissionRepository authRolePermissionRepository;
    @Autowired
    private AuthPermissionRepository authPermissionRepository;
    @Autowired
    private AuthAccountRoleRepository authAccountRoleRepository;
    @Autowired
    private AuthAccountRepository authAccountRepository;
    @Autowired
    private AuthOrgaService orgaService;


    public AuthRole save(AuthRoleForm authRoleForm) {
        AuthRole authRole = new AuthRole();
        BeanUtils.copyProperties(authRoleForm, authRole);
        if (StringUtil.isEmpty(authRoleForm.getId())) {
            log.debug("new role");
            authRole.setCrtDate(new Date());
            authRole.setRemoved(RemovedCodeEnum.AVAILABLE.getCode());
        }else{
            List<String> permissionIds=authRolePermissionRepository.findPermissionIdByRoleId(authRoleForm.getId());
            List<AuthPermission> list=authPermissionRepository.findAllById(permissionIds);
            authRole.setPres(new HashSet<>(list));
        }
        authRole.setUpdDate(new Date());
        log.debug("modify role");
        return repo.save(authRole);
    }

    //根据roleId 获得改角色的已有权限
    public List<AuthRolePermission> getCheckedPermission(String roleId) {
        return authRolePermissionRepository.findByRoleId(roleId);
    }


    //修改role的权限
    //@Transactional
    public void updateRolePermission(String roleId, String[] checkedKeys) {
        //先根据roleId删除原来的权限
        authRolePermissionRepository.deleteByRoleId(roleId);
        //判断数组是否有值
        if (checkedKeys.length > 0) {
            //在把新的权限新增到角色权限表里
            List<AuthRolePermission> list = new ArrayList<>();
            Map<String, Object> map = InitCommonSourceEnum.getCommonSource(CommonSourceKeyEnum.PERMISSION.name());
            List<String> pIds = new ArrayList<String>();
            //查询所有parentId为all的节点
            for (Map.Entry<String, Object> entry : map.entrySet()) {
                if (Objects.equals(((AuthPermission) entry.getValue()).getParentId(), "all")&& ((AuthPermission) entry.getValue()).getRemoved()==RemovedCodeEnum.AVAILABLE.getCode()) {
                    pIds.add(((AuthPermission) entry.getValue()).getId());
                }
            }
            //把选中的key放入list
            List<String> finalIds = new ArrayList<String>();
            for (int i = 0; i < checkedKeys.length; i++) {
                finalIds.add(checkedKeys[i]);
            }
            //循环所有parentId为all的节点  如果选中的节点中存在parentId为all的节点  就移除子节点
            for (String pid : pIds) {
                if (finalIds.contains(pid)) {
                    /*for (AuthPermission p : ((AuthPermission) map.get(pid)).getPerChildren()) {
                        finalIds.remove(p.getId());
                    }*/
                    finalIds=removeChildren(map,pid,finalIds);
                }
            }
            //移除根节点
            finalIds.remove("all");
            for (String checkedKey : finalIds) {
                AuthRolePermission authRolePermission = new AuthRolePermission();
                authRolePermission.setRoleId(roleId);
                authRolePermission.setPermissionId(checkedKey);
                authRolePermission.setCrtDate(new Date());
                authRolePermission.setUpdDate(new Date());
                authRolePermission.setRemoved(RemovedCodeEnum.AVAILABLE.getCode());
                list.add(authRolePermission);
            }
            authRolePermissionRepository.saveAll(list);
        }
    }

    /**
     * 移除所有子节点 只留parentId 为all的节点
     * @param map 机构树
     * @param pid 节点为all的某个id
     * @param finalIds 所有的选中key
     * @return
     */
    private List<String> removeChildren(Map map,String pid,List<String> finalIds){
        List<AuthPermission> list= ((AuthPermission) map.get(pid)).getPerChildren();
        for (AuthPermission p : list) {
            finalIds.remove(p.getId());
            if(!CollectionUtils.isEmpty(p.getPerChildren())){
                removeChildren(map,p.getId(),finalIds);
            }
        }

        return finalIds;
    }

    /**
     * 如果自己的角色里有admin  查询所有角色
     * 否则返回自己的所有角色
     */
    public List<SelectTreeNodeData> getRole(List<AuthRole> authRoleList) {

        for(AuthRole role : authRoleList){
            if(Objects.equals(role.getRoleCode(),"admin")){
                authRoleList = repo.findByRemoved(RemovedCodeEnum.AVAILABLE.getCode());
                break;
            }
        }
        List<SelectTreeNodeData> list = new ArrayList<>();
        for (AuthRole authRole : authRoleList) {
            SelectTreeNodeData selectTreeNodeData = new SelectTreeNodeData();
            selectTreeNodeData.setKey(authRole.getId());
            selectTreeNodeData.setValue(authRole.getRoleName());
            list.add(selectTreeNodeData);
        }
        return list;
    }

    //判断roleCode的唯一性
    public boolean checkUniqueRoleCode(String id,String roleCode){
        //修改
        if(!StringUtils.isEmpty(id)){
            // 1.如果没修改code 直接返回true 2.修改了code 判断修改后的code是否存在重复值
            AuthRole authRole= repo.findById(id).get();
            if(roleCode.equals(authRole.getRoleCode())){
                return true;
            }
        }

        //新增和修改都需要判断
        List<AuthRole> list=repo.findByRoleCodeAndRemoved(roleCode,RemovedCodeEnum.AVAILABLE.getCode());
        if(CollectionUtils.isEmpty(list)){
            return  true;
        }else {
            return false;
        }
    }

    //根据登录用户id查找角色（角色管理）
    public Page getRolesByAccountId(QueryForm form, HttpServletRequest request){
        Map<String, Object> params = form.getParams();
        //根据accountId 查询自己有的角色
        String accountId = String.valueOf(params.get("accountId"));
        //根据accountId查询该用户有的角色
        List<AuthAccountRole> accountRoles = authAccountRoleRepository.findByAccountId(accountId);
        //根据角色id查询所有角色
        List<AuthRole> authRoles1 = repo.findAllById(accountRoles.stream().map(e -> e.getRoleId()).collect(Collectors.toList()));
        Pageable pageable= PageRequest.of(form.getPageNum()-1,form.getPageSize());
        /**
         * 1.根据AccountId查出该用户绑定所有角色 List<AuthAccountRole>
         * 2.根据模糊查询字段结果过滤，得到最终结果 List<AuthRole>
         */
        String roleCode_Like = "%%";
        String roleName_Like = "%%";
        if(params.get("roleCode_like")!=null){
            roleCode_Like = String.valueOf("%" + params.get("roleCode_like") + "%");
        }if(params.get("roleName_like")!=null){
            roleName_Like = String.valueOf("%" + params.get("roleName_like") + "%");
        }
        List<AuthRole> authRoles2 = repo.findByRoleCodeLikeAndRoleNameLike(roleCode_Like,roleName_Like);
        List<AuthRole> authRoles = new ArrayList();

        for (AuthRole authRole:authRoles1){
            if(authRoles2.contains(authRole)){
                authRoles.add(authRole);
            }
        }
        return PageUtil.convertForPage(authRoles,pageable,authRoles.size());
    }



    public Page getUsersByRoleId(@RequestBody  QueryForm form){
        List<AuthAccount> list = new ArrayList();
        Map<String, Object> params = form.getParams();
        String roleId = String.valueOf(params.get("roleId_eq"));
        String accountLike =String.valueOf(params.get("account_like")).replace("null","");
        String userNameLike = String.valueOf(params.get("userName_like")).replace("null","");
        List<String> accountIds = authAccountRoleRepository.findAccountIdByRoleId(roleId);
        Pageable pageable= PageRequest.of(form.getPageNum()-1,form.getPageSize());
        for (String accountId: accountIds) {
            AuthAccount  authAccount = authAccountRepository.findAllById(accountId);
            if(authAccount.getAccount().contains(accountLike)&&authAccount.getUser().getUserName().contains(userNameLike))
            list.add(authAccount);
        }
        return PageUtil.convertForPage(list,pageable,list.size());
    }


    public Page getUsersWithoutRole(@RequestBody  QueryForm form,String orgaId){
        List<AuthAccount> list1 = new ArrayList();
        Map<String, Object> params = form.getParams();
        //按角色Id查出所有无该角色的用户
        String roleId = String.valueOf(params.get("roleId_eq"));
        List<String> otherAccountIds = authAccountRoleRepository.findOtheraccountByRoleId(roleId);
        Pageable pageable= PageRequest.of(form.getPageNum()-1,form.getPageSize());
        for (String accountId:otherAccountIds) {
            AuthAccount authAccount = authAccountRepository.findAllById(accountId);
            list1.add(authAccount);
        }
        //取交集过滤
        List<AuthAccount> list = new ArrayList();
        //查出该用户所属机构下的全部用户
        if("false".equals(params.get("isAdmin"))) {
            List<AuthOrga> authOrgas = orgaService.findAllOrgaByOrgaId(orgaId);
            for(AuthAccount authAccount:list1){
                for(AuthOrga authOrga : authOrgas){
                    if(authAccount.getDeptId().equals(authOrga.getId()))list.add(authAccount);
                }
            }
        }
        if("false".equals(params.get("isAdmin"))) {
            return PageUtil.convertForPage(list, pageable, list.size());
        }else {
            return PageUtil.convertForPage(list1, pageable, list1.size());
        }
    }
}